package com.car.loan.project.xr.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.car.loan.common.exception.loan.LoanParameterException;
import com.car.loan.common.utils.BeanUtils;
import com.car.loan.common.utils.SecurityUtils;
import com.car.loan.framework.web.domain.AjaxResult;
import com.car.loan.project.cm.domain.CmBank;
import com.car.loan.project.system.domain.SysUser;
import com.car.loan.project.xr.domain.Loan;
import com.car.loan.project.xr.domain.LoanCar;
import com.car.loan.project.xr.domain.LoanDetail;
import com.car.loan.project.xr.domain.LoanExt;
import com.car.loan.project.xr.domain.OverdueUrgentLog;
import com.car.loan.project.xr.mapper.LoanCarMapper;
import com.car.loan.project.xr.mapper.LoanDetailMapper;
import com.car.loan.project.xr.mapper.LoanExtMapper;
import com.car.loan.project.xr.mapper.LoanMapper;
import com.car.loan.project.xr.mapper.OverdueInfoMapper;
import com.car.loan.project.xr.mapper.OverdueUrgentLogMapper;
import com.car.loan.project.xr.service.impl.LoanServiceImpl;
import com.car.loan.project.xr.util.RedisDataUtil;
import com.car.loan.project.xr.util.bo.business.CustomerAddBo;
import com.car.loan.project.xr.util.bo.business.CustomerContactAddBo;
import com.car.loan.project.xr.util.bo.business.CustomerGuarantorAddBo;
import com.car.loan.project.xr.util.bo.business.after.OverdueUrgentLogBo;
import com.car.loan.project.xr.util.bo.business.after.OverdueUrgentLogPageParam;
import com.car.loan.project.xr.util.enums.CustomerMarry;
import com.car.loan.project.xr.util.enums.LoanStatusEnum;
import com.car.loan.project.xr.util.repayment.RepaymentFormulaInterface;
import com.car.loan.project.xr.util.repayment.RepaymentPlan;
import com.car.loan.project.xr.util.repayment.RepaymentPlanParam;
import com.car.loan.project.xr.util.repayment.RepaymentPlanUtil;
import com.car.loan.project.xr.util.vo.LoanDetailVo.LoanBaseInfoVo;
import com.car.loan.project.xr.util.vo.after.OverdueUrgentLogInfo;
import com.car.loan.project.xr.util.vo.after.OverdueUrgentLogVo;
import com.google.common.collect.Lists;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author huangding
 * @date 2020/2/26 19:36
 */
@Service
public class UrgentService {

    @Resource
    private OverdueUrgentLogMapper overdueUrgentLogMapper;

    @Autowired
    private LoanMapper loanMapper;

    @Autowired
    private LoanCarMapper loanCarMapper;

    @Autowired
    private LoanExtMapper loanExtMapper;

    @Autowired
    private LoanDetailMapper loanDetailMapper;

    @Autowired
    private RedisDataUtil redisDataUtil;

    @Autowired
    private LoanServiceImpl loanService;

    @Resource
    private OverdueInfoMapper overdueInfoMapper;

    public Page<OverdueUrgentLogVo> getOverdueUrgentLogPage(
        OverdueUrgentLogPageParam overdueUrgentLogPageParam) {
        Page page = new Page(overdueUrgentLogPageParam.getPageNum(),
            overdueUrgentLogPageParam.getPageSize());
        return overdueUrgentLogMapper.selectOverdueUrgentLogPage(page, overdueUrgentLogPageParam);
    }

    public OverdueUrgentLogInfo info(Long loanId) {
        OverdueUrgentLogInfo overdueUrgentLogInfo = new OverdueUrgentLogInfo();

        Optional<Loan> optionalLoan
            = Optional.ofNullable(loanMapper.selectById(loanId));
        Loan loan = optionalLoan.orElseThrow(() -> new LoanParameterException("无该业务数据"));
        //获取数据源
        Optional<LoanCar> optionalLoanCar = loanCarMapper.selectByLoanId(loanId);
        LoanCar loanCar = optionalLoanCar
            .orElseThrow(() -> new LoanParameterException("业务数据车辆信息异常"));
        Optional<LoanExt> optionalLoanExt = loanExtMapper.selectByLoanId(loanId);
        LoanExt loanExt = optionalLoanExt
            .orElseThrow(() -> new LoanParameterException("业务数据扩展信息异常"));

        Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
        LoanDetail loanDetail = optionalLoanDetail
            .orElseThrow(() -> new LoanParameterException("业务数据详情信息异常"));

        //客户信息
        overdueUrgentLogInfo
            .setCustomerInfo(loanService.getCustomerAddBo(loan.getId(), loan.getCustomerId()));
        //基本信息
        LoanBaseInfoVo loanBaseInfoVo = loanService.getLoanBaseInfoVo(loan);
        loanBaseInfoVo.setFileNo(loanDetail.getFileNo());
        overdueUrgentLogInfo.setLoanBaseInfo(loanBaseInfoVo);

        //业务信息
        OverdueUrgentLogInfo.BusinessInfo businessInfo = new OverdueUrgentLogInfo.BusinessInfo();
        BeanUtils.copyBeanProp(businessInfo, loanDetail);
        businessInfo.setBankName(redisDataUtil.getBankName(loan.getBankId()));
        businessInfo.setInstallmentAmount(loanExt.getInstallmentAmount());
        businessInfo.setRate(loanExt.getRate());
        businessInfo.setFinancingAmount(loanExt.getFinancingAmount());
        businessInfo.setTerm(loanExt.getTerm());
        businessInfo.setInstallmentAmount(loanExt.getInstallmentAmount());
        businessInfo.setRate(loanExt.getRate());
        businessInfo.setFinancingAmount(loanExt.getFinancingAmount());
        businessInfo.setTerm(loanExt.getTerm());
        overdueUrgentLogInfo.setBusinessInfo(businessInfo);

        //车辆信息
        OverdueUrgentLogInfo.CarInfo carInfo = new OverdueUrgentLogInfo.CarInfo();
        BeanUtils.copyBeanProp(carInfo, loanCar);
        overdueUrgentLogInfo.setCarInfo(carInfo);

        //逾期信息
        OverdueUrgentLogInfo.OverdueInfo overdueInfo = new OverdueUrgentLogInfo.OverdueInfo();
        overdueInfo.setOverdueAmount(loanExt.getOverdueAmount());
        overdueInfo.setAdvancesAmount(loanExt.getAdvancesAmount());
        overdueInfo.setOverdueMaxAmount(loanExt.getOverdueMaxAmount());
        overdueInfo.setOverdueTerm(loanExt.getOverdueTerm());
        overdueInfo.setOverdueCount(loanExt.getOverdueCount());
        Optional<com.car.loan.project.xr.domain.OverdueInfo> optionalOverdueInfo = overdueInfoMapper
            .selectOneByLoanIdAndItem(loanId, loanExt.getOverdueTerm());
        optionalOverdueInfo
            .ifPresent(info -> {
                overdueInfo.setCurrentOverdueMaxAmount(info.getMaxOverdueAmount());
                overdueInfo.setCurrentPayableAmount(info.getPayableAmount());
            });
        overdueUrgentLogInfo.setOverdueInfo(overdueInfo);

        //催收记录
        overdueUrgentLogInfo.setUrgentLogs(Lists.newArrayList());

        List<OverdueUrgentLog> overdueUrgentLogs = overdueUrgentLogMapper.selectByLoanId(loanId);
        if (null != overdueUrgentLogs && overdueUrgentLogs.size() > 0) {
            Map<String, SysUser> redisUserMap = redisDataUtil.getRedisUserMap();
            List<OverdueUrgentLogInfo.UrgentLog> urgentLogs = new ArrayList<>();
            overdueUrgentLogs.forEach(overdueUrgentLog -> {
                OverdueUrgentLogInfo.UrgentLog urgentLog = new OverdueUrgentLogInfo.UrgentLog();
                BeanUtils.copyBeanProp(urgentLog, overdueUrgentLog);
                urgentLog.setAdminName(
                    redisUserMap.get(overdueUrgentLog.getCreatorId().toString()).getUserName());
                urgentLogs.add(urgentLog);
            });
            overdueUrgentLogInfo.setUrgentLogs(urgentLogs);
        }
        CmBank cmBank = redisDataUtil.getRedisBankMap().get(loan.getBankId().toString());
        //还款计划获取
        RepaymentFormulaInterface repaymentFormulaInterface = new RepaymentFormulaInterface() {
        };
        RepaymentPlanParam repaymentPlanParam = new RepaymentPlanParam();
        repaymentPlanParam.setFinancingAmount(new BigDecimal(loanExt.getFinancingAmount()));
        repaymentPlanParam.setFirstStatementDate(loanDetail.getFirstRepayDate());
        repaymentPlanParam.setGracePeriod(cmBank.getGracePeriod());
        repaymentPlanParam.setTerm(Integer.parseInt(loanExt.getTerm().toString()));
        repaymentPlanParam.setMonthRepayInterest(loanDetail.getMonthRepayInterest());
        repaymentPlanParam.setMonthRepayPrincipal(loanDetail.getMonthRepayPrincipal());
        repaymentPlanParam.setFirstRepayInterest(loanDetail.getFirstRepayInterest());
        repaymentPlanParam.setFirstRepayPrincipal(loanDetail.getFirstRepayPrincipal());
        repaymentPlanParam.setLastRepayInterest(loanDetail.getLastRepayInterest());
        repaymentPlanParam.setLastRepayPrincipal(loanDetail.getLastRepayPrincipal());
        List<RepaymentPlan> repaymentPlans = repaymentFormulaInterface
            .getRepaymentPlans(repaymentPlanParam);
        overdueUrgentLogInfo.setRepaymentPlans(repaymentPlans);
        RepaymentPlan repaymentPlan = repaymentPlans.get(overdueInfo.getOverdueTerm() - 1);
        overdueInfo.setCurrentMonthlyRepayment(repaymentPlan.getMonthRepayAmount());
        overdueUrgentLogInfo.setOverdueInfo(overdueInfo);

        //联系人封装
        List<OverdueUrgentLogInfo.RelationshipInfo> relationshipInfos = new ArrayList<>();
        CustomerAddBo customerInfo = overdueUrgentLogInfo.getCustomerInfo();

        OverdueUrgentLogInfo.RelationshipInfo customerRelationshipInfo = new OverdueUrgentLogInfo.RelationshipInfo();
        customerRelationshipInfo.setName(customerInfo.getCustomerInfo().getName());
        customerRelationshipInfo.setMobile(customerInfo.getCustomerInfo().getMobile());
        customerRelationshipInfo.setRelationship("借款人");
        relationshipInfos.add(customerRelationshipInfo);

        if (null != customerInfo.getCustomerGuarantors()) {
            for (CustomerGuarantorAddBo guarantorAddBo : customerInfo.getCustomerGuarantors()) {
                OverdueUrgentLogInfo.RelationshipInfo guarantorRelationshipInfo = new OverdueUrgentLogInfo.RelationshipInfo();
                guarantorRelationshipInfo.setName(guarantorAddBo.getName());
                guarantorRelationshipInfo.setMobile(guarantorAddBo.getMobile());
                guarantorRelationshipInfo.setRelationship("担保人");
                relationshipInfos.add(guarantorRelationshipInfo);
            }
        }
        if (null != customerInfo.getCustomerContacts()) {
            for (CustomerContactAddBo customerContactAddBo : customerInfo.getCustomerContacts()) {
                OverdueUrgentLogInfo.RelationshipInfo customerContactRelationshipInfo = new OverdueUrgentLogInfo.RelationshipInfo();
                customerContactRelationshipInfo.setName(customerContactAddBo.getName());
                customerContactRelationshipInfo.setMobile(customerContactAddBo.getMobile());
                customerContactRelationshipInfo
                    .setRelationship("联系人");
                relationshipInfos.add(customerContactRelationshipInfo);
            }
        }
        if (CustomerMarry.MARRIED.status == customerInfo.getCustomerInfo().getMarry()) {
            OverdueUrgentLogInfo.RelationshipInfo customerSpouseRelationshipInfo = new OverdueUrgentLogInfo.RelationshipInfo();
            customerSpouseRelationshipInfo.setName(customerInfo.getCustomerSpouse().getName());
            customerSpouseRelationshipInfo.setMobile(customerInfo.getCustomerSpouse().getMobile());
            customerSpouseRelationshipInfo.setRelationship("配偶");
            relationshipInfos.add(customerSpouseRelationshipInfo);
        }
        overdueUrgentLogInfo.setRelationshipInfos(relationshipInfos);
        return overdueUrgentLogInfo;
    }

    public AjaxResult input(OverdueUrgentLogBo overdueUrgentLogBo) {
        OverdueUrgentLog overdueUrgentLog = new OverdueUrgentLog();
        BeanUtils.copyBeanProp(overdueUrgentLog, overdueUrgentLogBo);
        overdueUrgentLog.setRelationship(overdueUrgentLogBo.getRelationship());
        overdueUrgentLog.setCreatorId(SecurityUtils.getLoginUserId());
        overdueUrgentLog.setCreateTime(LocalDateTime.now());
        overdueUrgentLogMapper.insert(overdueUrgentLog);
        if (2 == overdueUrgentLogBo.getRepaymentStatus()) {
            repayment(overdueUrgentLogBo.getLoanId());
        }
        return AjaxResult.success();
    }

    public AjaxResult repayment(Long loanId) {
        Loan loan = loanMapper.selectById(loanId);
        loan.setBusinessStatus(LoanStatusEnum.NORMAL_PAYMENT.status);
        loanMapper.updateById(loan);

        Optional<LoanExt> optionalLoanExt = loanExtMapper.selectByLoanId(loanId);
        if (optionalLoanExt.isPresent()) {
            LoanExt loanExt = optionalLoanExt.get();
            loanExt.setOverdueAmount(0D);
            loanExtMapper.updateById(loanExt);
        }
        return AjaxResult.success();
    }
}
